/**
 *
 */
package com.oron3.locker;

import java.io.File;
import java.util.ArrayList;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;

import com.ofek.db.Table;

/**
 * @author Ofek
 *
 */
public class LockDatabase {
	private final Table<SecretID> idTable;
	private final Table<Secret> secretTable;
	private final SQLiteDatabase sqldb;
	private AES aes;

	/**
	 * @param lock
	 * @param password
	 *
	 */
	private LockDatabase(final LockApplication lock, String password) {
		sqldb = lock.openOrCreateDatabase("LockV1", Context.MODE_PRIVATE, null);
		idTable = new Table<SecretID>(sqldb, SecretID.class);
		secretTable = new Table<Secret>(sqldb, Secret.class);
		try {
			aes = new AES(password);
		} catch (final Exception e) {
			e.printStackTrace();
		}
	}

	private boolean oldVersionExists(LockApplication lock) {
		final File dbFile = lock.getDatabasePath("Lock");
		return dbFile.exists();
	}

	public static LockDatabase getInstance(String password) {
		return new LockDatabase(LockApplication.context, password);
	}

	public SecretHolder getHolder(final SecretID secret) {
		final ArrayList<Secret> all = secretTable.getAll("sid=" + secret.sid);
		final ArrayList<Secret> decrypted = new ArrayList<Secret>();
		for (final Secret s : all) {
			try {
				decrypted.add(new Secret(0, aes.decrypt(s.secretTitle), aes.decrypt(s.secret)));
			} catch (final Exception e) {
				e.printStackTrace();
			}
		}
		return new SecretHolder(secret, decrypted);
	}

	/**
	 * @param secret
	 * @return
	 */
	public void add(final SecretHolder secret) {
		final SecretHolder encrypted = encrypt(secret);
		final long id = idTable.add(encrypted.id);
		for (final Secret s : encrypted.secrets) {
			s.sid = id;
			secretTable.add(s);
		}
	}

	private SecretHolder encrypt(SecretHolder secret) {
		final SecretHolder secretHolder = new SecretHolder();
		try {
			secretHolder.id = new SecretID(secret.id.sid, aes.encrypt(secret.id.title));
			for (final Secret s : secret.secrets) {
				secretHolder.add(new Secret(0, aes.encrypt(s.secretTitle), aes.encrypt(s.secret)));
			}
		} catch (final Exception e) {
			e.printStackTrace();
		}
		return secretHolder;
	}

	private SecretHolder decrypt(SecretHolder secret) {
		final SecretHolder secretHolder = new SecretHolder();
		try {
			secretHolder.id = new SecretID(secret.id.sid, aes.decrypt(secret.id.title));
			for (final Secret s : secret.secrets) {
				secretHolder.add(new Secret(0, aes.decrypt(s.secretTitle), aes.decrypt(s.secret)));
			}
		} catch (final Exception e) {
			e.printStackTrace();
		}
		return secretHolder;
	}

	public void release() {
		sqldb.close();
	}

	/**
	 * @param secret
	 * @param actualSecret
	 */
	public void remove(final Secret actualSecret) {
		secretTable.remove(actualSecret);
	}

	/**
	 * @param secret
	 * @param actualSecret
	 */
	public void remove(final SecretHolder secret) {
		idTable.remove(secret.id);
	}

	/**
	 * @return
	 *
	 */
	public ArrayList<SecretID> getAllIDs() {
		final ArrayList<SecretID> all = idTable.getAll();
		final ArrayList<SecretID> decrypted = new ArrayList<SecretID>();
		for (final SecretID id : all) {
			try {
				decrypted.add(new SecretID(id.sid, aes.decrypt(id.title)));
			} catch (final Exception e) {
				e.printStackTrace();
			}
		}
		return decrypted;
	}

	/**
	 * @param secretID
	 */
	public void remove(final SecretID secretID) {
		idTable.remove(secretID);
	}

	/**
	 * @param secret
	 */
	public void replace(final SecretHolder secret) {
		final SecretHolder encrypted = encrypt(secret);
		final long id = idTable.replace(encrypted.id);
		for (final Secret s : encrypted.secrets) {
			s.sid = id;
			secretTable.add(s);
		}
	}

}
